#Copyright 2011 Mohit Shah

#This file is part of soundblogs-python.

#soundblogs-python is free software: you can redistribute it and/or modify
#it under the terms of the GNU General Public License as published by
#the Free Software Foundation, either version 3 of the License, or
#(at your option) any later version.

#soundblogs-python is distributed in the hope that it will be useful,
#but WITHOUT ANY WARRANTY; without even the implied warranty of
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#GNU General Public License for more details.

#You should have received a copy of the GNU General Public License
#along with soundblogs-python.  If not, see <http://www.gnu.org/licenses/>.

#The routine for computing the LPC coefficients is based on 
#source code included in the Ogg/Vorbis audio codec developed by xiph.org.

import numpy as np
import scipy.signal as sig

class Build:
    def __init__(self,num_coeff):
        self.value = []
        self.num_coeff = num_coeff
    def calculate(self,data):
        ncoeff = self.num_coeff
        acorr = np.zeros(ncoeff+1)
        lpc = np.zeros(ncoeff)
        i = j = 0
        j = ncoeff + 1
        n = len(data)
        while j>0:
            j = j-1
            d = 0
            for i in range(j,n):
                d = d + data[i]*data[i-j] 
            acorr[j] = d
        error = acorr[0]
        for i in range(0,ncoeff):
            r = -acorr[i+1]
            for j in range(0,i):
                r = r - lpc[j]*acorr[i-j]
            r = r/error
            lpc[i] = r
            for j in range(0,i/2):
                temp = lpc[j]
                lpc[j] = lpc[j] + (r*lpc[i-1-j])
                lpc[i-1-j] = lpc[i-1-j] + (r*temp)
            if i%2:
                lpc[j] = lpc[j] + lpc[j]*r
            error = error * (1 - (r*r))  
        lpc = -lpc
        lpc = np.insert(lpc,0,1)
        coeff = lpc
        filt = sig.lfilter(coeff,1,data)
        residue = data - filt
        error = np.sqrt(np.dot(residue,residue))/len(data)
        return error
    def store(self,data):
        self.value.append(data)
    def getValues(self):
        return self.value
